﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;

using eBookDomain;
using eBookDataAccess;
using eBook.Domain;
using eBook.Core;
using eBook.Core.BusinessObjects;

namespace eBookWinApp
{
  public class BookRenamer
  {
    private AWSSearchEngine _aws = new AWSSearchEngine();
    private NHibernateDataProvider _provider;
    private NHibernateSessionManager _sessionManager;    
    private boBookInfo _searchResult;

    public string LibraryBaseFolder
    {
      get;
      set;
    }
    public string SourceFilePath
    {
      get;
      set;
    }
    public string DestinationFilePath
    {
      get;
      set;
    }
    
    public BookRenamer()
    {
      // AccessKey        1REKPA0HEES4TPN9ZE02   
      // Secret AccessKey 4pI0a2ZyLXdGI8bOMj7aD/04I2ao9FAF8jpZYMao      
      _aws.SubscriptionId = "1WRF74XYWAF1YEEE1YG2";
      _aws.SearchIndex = SearchIndex.Books;
      _aws.ResponseGroup = new string[] { "ItemAttributes", "Images", "EditorialReview" };    

      _sessionManager = new NHibernateSessionManager();
      _provider = new NHibernateDataProvider(_sessionManager.GetSession());    
    }
    
    public boBookInfo Search(ISBN isbn)
    {
      if (isbn == null)
        return null;
      
      _searchResult = null;
          
      _aws.Criteria.Reset();
      _aws.Criteria.ISBN = isbn.StrippedISBN;
      _aws.Search();
      if ( _aws.Books.Count != 0 )
      {
        _searchResult = _aws.Books[0];
        this.DestinationFilePath = SuggestNewFilePath( isbn, _searchResult );
      }
      
      return _searchResult;
    }

    private string SuggestNewFilePath( ISBN isbn, boBookInfo awsBook )
    {      
      if ( string.IsNullOrEmpty(this.SourceFilePath) )
        return string.Empty;
      
      if ( !File.Exists(this.SourceFilePath) )
        return string.Empty;
        
      #region Build folder name  
      
      string newFolderName = string.Empty;
      string[] iParts = isbn.Hyphenate().Split( '-' );
      if ( iParts.Length >= 4 )
        newFolderName = string.Format("{0}\\{1}\\{2}"
                                    , this.LibraryBaseFolder 
                                    , iParts[0] 
                                    , iParts[1]);
      else
        newFolderName = string.Format("{0}\\{1}"
                                    , this.LibraryBaseFolder 
                                    , iParts[0]);

      #endregion  
      
      #region Build file name 
      FileInfo f = new FileInfo( this.SourceFilePath );
      string newFilePath = string.Format( "{0}\\[{1}] {2}{3}"
                                        , newFolderName
                                        , isbn.Hyphenate()
                                        , ReplaceInvalidFilenameChar( awsBook.Title )
                                        , f.Extension ); 
      #endregion
                                                                                
      return newFilePath;
    }      
  
    public void Rename()
    {
      if ( _searchResult == null)
        return;

      #region Persist book entity 
      
      Book book = ConvertInfoToEntity( _searchResult );
      if ( book != null )
        _provider.SaveOrUpdate( book ); 
           
      #endregion              
            
          
      #region Move file 
      
      if ( File.Exists(this.DestinationFilePath))
        return;    
        
      string destinationFolder = Path.GetDirectoryName( this.DestinationFilePath );      
      if ( !Directory.Exists( destinationFolder ) )
        Directory.CreateDirectory( destinationFolder );  
        
      FileInfo f = new FileInfo( this.SourceFilePath );
      f.MoveTo( this.DestinationFilePath );    
      
      book.FilePath = destinationFolder;
      book.FileName = f.Name;     
      _provider.SaveOrUpdate(book);
       
      #endregion 
    

         
    }
    
    public Book ConvertInfoToEntity(boBookInfo awsBook)
    {      
      Book book = TryToGetBookByISBN(awsBook);
      if (book == null)      
        book = new Book();
        
      ISBN isbn10 = new ISBN10(awsBook.ISBN10);
      book.ISBN10 = isbn10.Hyphenate();
      book.ISBN13 = new ISBN13(isbn10.Transform()).Hyphenate();
      
      book.ASIN   = awsBook.ASIN;
      book.DeweyDecimal  = awsBook.DeweyDecimalNumber;
      
      book.Title   = awsBook.Title;
      book.Edition = awsBook.Edition;
      
      if ( !string.IsNullOrEmpty(awsBook.NumberOfPages) )
        book.NumberOfPages = Convert.ToInt32(awsBook.NumberOfPages);
        
      book.EditorialReview = awsBook.EditorialReview;
      
      book.AmazonRating = awsBook.AudienceRating;
      book.PublicationDate = awsBook.PublicationDate;
      
      book.SmallImageURL = awsBook.SmallImageURL;
      book.MediumImageURL = awsBook.MediumImageURL;
      book.LargeImageURL = awsBook.LargeImageURL;
      book.DateCreated = DateTime.Now;
      
      foreach ( string author in awsBook.Authors )
      {
        bool hasAuthor = 1 == book.Authors.Count<Author>( x => x.Name == author );      ;
        if ( !hasAuthor )
          book.Authors.Add(new Author(){Name = author});
      }
            
      bool hasLink = 1 == book.Links.Count<Link>( x => x.Path == awsBook.DetailPageURL );      
      if ( !hasLink )
        book.Links.Add(new Link(){Name = "Amazon detail page", Path = awsBook.DetailPageURL});
      
      Publisher p =_provider.GetPublisherByName(awsBook.Publisher);
      if ( p == null )
        p = new Publisher(){Name=awsBook.Publisher};
        
      book.Publisher = p;  
      
      return book;
    }  
    
    private Book TryToGetBookByISBN(boBookInfo awsBook)
    {
      Book result = null;
      
      ISBN13 isbn13 = null;
      ISBN10 isbn10 = new ISBN10(awsBook.ISBN10);    
      
      result = _provider.GetBookByISBN( isbn10.Hyphenate() );      
      if (result != null)
        return result;
        
      isbn13 = new ISBN13(isbn10.Transform());
      result = _provider.GetBookByISBN( isbn13.Hyphenate() );      
      if (result != null)
        return result;
        
      isbn13 = new ISBN13(awsBook.ISBN13);
      result =_provider.GetBookByISBN( isbn13.Hyphenate() );
      if ( result != null)
        return result;

      isbn10 = new ISBN10(isbn13.Transform());
      result = _provider.GetBookByISBN( isbn10.Hyphenate() );
      
      return result;
    }
    

    
    private string ReplaceInvalidFilenameChar(string filename)
    {
      string result = new Regex(@"[:\\/?<>|\*]").Replace(filename, " ");
      return result;
    }
    
  
  }
}
